<template>
  <div class="body">
    <div class="menu">
      <div>
        <span>请输入资源地址:</span>
        <input v-model="fileName" />
        <button @click="initFile">加载</button>
      </div>
      <div>读取 点[{{ points.length }}],面[{{ lines.length }}]</div>
      <div>
        <button v-on:click="
						() => {
							type = 1;
							init();
						}
					">点</button>
        <button v-on:click="
						() => {
							type = 2;
							init()
						}
					">线</button>
        <button v-on:click="
						() => {
							type = 3;
							init()
						}
					">面</button>
      </div>
      <div>
        <button v-on:click="setAngleX">x</button>
        <button v-on:click="setAngleY">y</button>
        <button v-on:click="setAngleZ">z</button>
      </div>
      <div class="msg" v-for="(item, index) in params.params">
        <button
          v-on:click="
						() => {
							material = index;
							init();
						}
					"
        >{{ item }}</button>
      </div>
    </div>
    <div id="canvas" ref="canvas" class="hello"></div>
  </div>
</template>

<script>
import * as THREE from "three";
// import TrackballControls from 'three-trackballcontrols';
import Orbitcontrols from "three-orbitcontrols";
import fontjson from "three/examples/fonts/helvetiker_regular.typeface.json";

import { parse } from "../utils/file.js";
import { dispColor, ps, cs } from "../utils/color.js";

export default {
  name: "HelloWorld",
  data() {
    return {
      params: { params: [] },
      material: 0,
      type: 3,
      fileName:
        "https://gangmao.oss-cn-shenzhen.aliyuncs.com/InputModel_NodalInfo_TecplotWithGeoFrac_0001.dat"
    };
  },
  created() {
    this.initFile();
  },
  mounted() {
    console.log("mounted");
    // 初始化 渲染器
    console.log("initThree");
    this.initThree();
    // 初始化 场景
    console.log("initScene");
    this.initScene();
    // 初始化 摄影机
    console.log("initCamera");
    this.initCamera();
    // 添加镜头控制器
    console.log("initControls");
    this.initControls();

    this.init();

    requestAnimationFrame(this.render);
    console.log("json", fontjson);
  },
  methods: {
    initFile() {
      this.params = parse(this.fileName);
      this.params.params = this.params.params.slice(
        0,
        this.params.params.length - 1
      );
      this.points = this.params.points;
      this.lines = this.params.lines;
    },
    init() {
      this.initScene();
      switch (this.type) {
        case 1:
          this.initPoint();
          break;
        case 2:
          this.initLine();
          break;
        case 3:
          this.initGeometry();
          break;
      }
      this.initColor();
    },
    initPoint() {
      const geometry = new THREE.BufferGeometry(); //声明一个缓冲几何体对象
      geometry.computeBoundingBox();
      let vertices = [];
      let colors = [];
      const { min, max } = this.params.params[this.material]; // 获取 灰阶 最大最小值 （解析文件获得）

      this.points.forEach(point => {
        vertices.push(...point.slice(0, 3));
        const cs = dispColor(min, max, point[this.material]);
        colors.push(...cs);
      });

      //类型数组创建顶点位置position数据
      vertices = new Float32Array(vertices);
      // 创建属性缓冲区对象
      const attribue = new THREE.BufferAttribute(vertices, 3); //3个为一组，作为一个顶点的xyz坐标
      // 设置几何体attributes属性的位置position属性
      geometry.setAttribute("position", attribue);
      //类型数组创建顶点颜色color数据
      colors = new Float32Array(colors);

      // 设置几何体attributes属性的颜色color属性
      const colorBufferAttribute = new THREE.BufferAttribute(colors, 3);
      geometry.setAttribute("color", colorBufferAttribute);
      //材质对象
      const material = new THREE.MeshBasicMaterial({
        vertexColors: true //以顶点颜色为准
      });
      // 点渲染模式  点模型对象Points
      const points = new THREE.Points(geometry, material); //点模型对象

      this.scene.add(points);
    },
    initLine() {
      const group = new THREE.Object3D();
      const material = new THREE.MeshBasicMaterial({
        vertexColors: THREE.VertexColors
      });
      const { min, max } = this.params.params[this.material]; // 获取 灰阶 最大最小值 （解析文件获得）
      this.lines.forEach(arrs => {
        const geometry = new THREE.BufferGeometry();
        var ps = [];
        let colors = [];
        arrs.forEach(arr => {
          const point = this.points[arr - 1];
          ps.push(new THREE.Vector3(point[0], point[1], point[2]));
          const cs = dispColor(min, max, point[this.material]);
          colors.push(...cs);
        });

        geometry.setFromPoints(ps);

        colors = new Float32Array(colors);
        const colorBufferAttribute = new THREE.BufferAttribute(colors, 3);
        geometry.setAttribute("color", colorBufferAttribute);

        var line = new THREE.Line(geometry, material);
        group.add(line);
      });
      this.scene.add(group);
    },
    initGeometry() {
      const { min, max } = this.params.params[this.material]; // 获取 灰阶 最大最小值 （解析文件获得）
      // 材质
      const material = new THREE.MeshBasicMaterial({
        vertexColors: THREE.VertexColors,
        side: THREE.DoubleSide
      });

      let verticeTotals = [];
      let colorTotals = [];
      let pss = [];

      var temp = {};

      function rd(a, b, c) {
        const key = `${a.key}${b.key}${c.key}`;
        if (temp[key] !== 0 && !temp[key]) {
          temp[key] = 0;
          verticeTotals.push(...a.points, ...b.points, ...c.points);
          colorTotals.push(...a.colors, ...b.colors, ...c.colors);
        } else {
          temp[key] += 1;
        }
      }

      // 四面体
      this.lines.forEach((arrs, index) => {
        // 四面体 点集合
        const points = [];
        // 获取顶点
        arrs.forEach((arr, index) => {
          const point = this.points[arr - 1]; //点
          const cs = dispColor(min, max, point[this.material]); //颜色
          points.push({
            key: point[point.length - 1],
            points: point.slice(0, 3),
            colors: cs
          });
        });
        for (let i = 0; i < points.length; i++) {
          for (let j = 0; j < points.length - i - 1; j++) {
            if (points[j] > points[j + 1]) {
              let temp = points[j];
              points[j] = points[j + 1];
              points[j + 1] = temp;
            }
          }
        }

        // 获取面

        rd(points[0], points[1], points[2]);
        rd(points[0], points[1], points[3]);
        rd(points[0], points[2], points[3]);
        rd(points[1], points[2], points[3]);
      });
      console.log(verticeTotals.length);

      verticeTotals = new Float32Array(verticeTotals);
      colorTotals = new Float32Array(colorTotals);
      // itemSize = 3 因为每个顶点都是一个三元组。
      const bufferAttribute = new THREE.BufferAttribute(verticeTotals, 3);
      const colorBufferAttribute = new THREE.BufferAttribute(colorTotals, 3);
      const geometry = new THREE.BufferGeometry();
      geometry.computeBoundingBox();
      geometry.setAttribute("color", colorBufferAttribute);
      geometry.setAttribute("position", bufferAttribute);
      const mesh = new THREE.Mesh(geometry, material);

      this.scene.add(mesh);
    },
    // 初始化 渲染器
    initThree() {
      this.width = this.$refs.canvas.offsetWidth;
      this.height = this.$refs.canvas.offsetHeight;
      console.log(this.width, this.height);
      this.renderer = new THREE.WebGLRenderer({
        antialias: true
      });
      console.log("initThree 1");
      this.renderer.setSize(this.width, this.height);
      console.log("initThree 2");
      this.renderer.setClearColor(0x000000, 1.0);
      // document.body.appendChild(this.renderer.domElement);
      this.$refs.canvas.appendChild(this.renderer.domElement);
    },
    // 初始化 场景
    initScene() {
      if (this.scene) {
        this.scene.children.forEach(item => {
          this.scene.remove(item);
        });
      } else {
        this.scene = new THREE.Scene();
      }
    },
    // 初始化 摄影机
    initCamera() {
      const { x, y, z } = this.params.lookup;
      this.camera = new THREE.PerspectiveCamera(
        45,
        this.width / this.height,
        1,
        10000
      );
      this.camera.position.x = x;
      this.camera.position.y = y;
      this.camera.position.z = z * 20;

      // this.camera.set(x,y,z); // 设置摄影机位置
      // this.camera.up(0, 1, 0); // 向上的坐标 默认y轴
      this.camera.lookAt(new THREE.Vector3(x, y, z));
    },
    initColor() {
      this.group = new THREE.Group();
      // this.axis = new THREE.AxisHelper(1);
      // 材质
      const material = new THREE.MeshBasicMaterial({
        vertexColors: THREE.VertexColors,
        side: THREE.DoubleSide
      });
      var verticeTotals = new Float32Array(ps);
      var colorTotals = new Float32Array(cs);
      // itemSize = 3 因为每个顶点都是一个三元组。
      const bufferAttribute = new THREE.BufferAttribute(verticeTotals, 3);
      const colorBufferAttribute = new THREE.BufferAttribute(colorTotals, 3);
      const geometry = new THREE.BufferGeometry();
      geometry.computeBoundingBox();
      geometry.setAttribute("color", colorBufferAttribute);
      geometry.setAttribute("position", bufferAttribute);
      const colorMesh = new THREE.Mesh(geometry, material);
      colorMesh.position.set(-4.7, 0, -10);
      this.group.add(colorMesh);

      const font = this.params.params[this.material];
      const step = (font.max - font.min) / 4;
      var loader = new THREE.FontLoader();

      var textGeometry = new THREE.TextBufferGeometry(font.name, {
        font: loader.parse(fontjson),
        size: 1,
        height: 0
      });
      const fontMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff });
      let textMesh = new THREE.Mesh(textGeometry, fontMaterial);
      textMesh.position.set(-4.6, 10, -10);
      this.group.add(textMesh);

      for (var i = 0; i <= 4; i++) {
        var textGeometry = new THREE.TextBufferGeometry(
          `${Number(font.min + i * step).toFixed(2)}`,
          {
            font: loader.parse(fontjson),
            size: 0.5,
            height: 0
          }
        );
        const fontMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff });
        let textMesh = new THREE.Mesh(textGeometry, fontMaterial);
        textMesh.position.set(-3, 0 + i * 2.14, -10);
        this.group.add(textMesh);
      }

      this.scene.add(this.group);
    },
    // 变动更新
    changeColor() {
      this.group.position.copy(this.camera.position);
      this.group.rotation.copy(this.camera.rotation);
      this.group.updateMatrix();
      this.group.translateZ(-20);
      this.group.translateX(-15);
      this.group.translateY(-5);
    },
    // 初始化 摄影机控制器
    initControls() {
      // this.trackballControls = new TrackballControls(this.camera);
      // this.trackballControls.rotateSpeed = 1.0;
      // this.trackballControls.zoomSpeed = 1.0;
      // this.trackballControls.panSpeed = 1.0;
      const { x, y, z } = this.params.lookup;
      this.orbitcontrols = new Orbitcontrols(
        this.camera,
        this.renderer.domElement
      );
      this.orbitcontrols.target = new THREE.Vector3(x, y, z);
      this.orbitcontrols.enablePan = false;
      this.orbitcontrols.enableKeys = false;
      // this.orbitcontrols.autoRotate = true;
      this.clock = new THREE.Clock();
      console.log(this.orbitcontrols);
    },
    setAngleX() {
      console.log(this.orbitcontrols);
      this.orbitcontrols.setAngleX();
    },
    setAngleY() {
      this.orbitcontrols.setAngleY();
    },
    setAngleZ() {
      this.orbitcontrols.setAngleZ();
    },
    render() {
      this.changeColor();
      var delta = this.clock.getDelta();
      this.orbitcontrols.update(delta);
      this.renderer.render(this.scene, this.camera);
      requestAnimationFrame(this.render);
    }
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
#canvas {
  flex: 3;
  border: none;
  width: 100%;
  height: 800px;
}
.body {
  display: flex;
  flex-direction: row;
  color: #010059;
  color: #0200b6;
  color: #0025cf;
  color: #0f83ce;
  color: #21d384;
  color: #5ed359;
  color: #b5d314;
  color: #ce8607;
  color: #cd2b07;
  color: #580002;
}
.menu {
  flex: 1;
}
</style>
